package quick.start.ui.widget;

import quick.start.core.util.CoreLog;
import quick.start.ui.R;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MonthDisplayHelper;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

public class TabSwitcher extends FrameLayout implements View.OnClickListener, View.OnTouchListener {

	private static final String TAG = "TabSwitcher";
	private static final int SWITCH_DURATION = 300;
	private static final int DEFAULT_FONTSIZE = 14;
	private static final int HORIZONTAL = 0;
	private static final int VERTICAL = 1;
	
	private Context context;
	private int arrayId;
	private int background;
	private int bgIndicator;
	private float textSize;
	private ColorStateList textColor;
	private int orientation;
	private boolean canDrag;
	
	private OnItemClickListener onItemClickListener;
	private String[] itemText;
	private TextView[] tvItem;
	private ImageView ivIndicator;
	private int indicatorLength;
	private int currPos;
	private int lastPos;
	private int touchXYPair[] = new int[]{0,0};
    private Interpolator interpolator  = new AccelerateDecelerateInterpolator();
	
	public interface OnItemClickListener{
		void onItemClick(View view, int position);
	}
	
	public TabSwitcher(Context context){
		super(context);
		init();
	}
	
	public TabSwitcher(Context context, AttributeSet attrs) {
		super(context, attrs);
		CoreLog.i(TAG, "Create TabSwitcher With AttributeSet");
		init();
		
		TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TabSwitcher);
		this.orientation = ta.getInt(R.styleable.TabSwitcher_tabOrientation, HORIZONTAL);
		this.arrayId = ta.getResourceId(R.styleable.TabSwitcher_arrayId, 0);
		this.background = ta.getResourceId(R.styleable.TabSwitcher_bg, 0);
		this.bgIndicator = ta.getResourceId(R.styleable.TabSwitcher_indicator, 0);
		this.textSize = ta.getDimension(R.styleable.TabSwitcher_fontSize, DEFAULT_FONTSIZE);
		this.textColor = ta.getColorStateList(R.styleable.TabSwitcher_fontColor);
		this.canDrag = ta.getBoolean(R.styleable.TabSwitcher_canDrag, false);
		ta.recycle();
	}
	
	public void setOnItemClickListener(OnItemClickListener listener){
		this.onItemClickListener = listener;
	}
	
	@Override
	public boolean onTouch(View v, MotionEvent event) {
		if(!this.canDrag){
			return false;
		}
		
		int action = event.getAction();
		int xOffset = (int)event.getRawX() - getLeft();
		int yOffset = (int)event.getRawY() - getTop();
		
		switch(action){
			case MotionEvent.ACTION_UP:
				this.tvItem[this.lastPos].setClickable(true);
				moveToAppropriatePosition();
				if(this.lastPos != this.currPos && null != onItemClickListener){
					onItemClickListener.onItemClick(this.tvItem[this.currPos], this.currPos);
				}
				this.lastPos = this.currPos;
				this.tvItem[this.currPos].setClickable(false);
				break;
			case MotionEvent.ACTION_DOWN:
				this.touchXYPair[0] = (int)event.getX();
				this.touchXYPair[1] = (int)event.getY();
				v.postInvalidate();
				break;
			case MotionEvent.ACTION_MOVE:
				int left = isHorizontal() ? (xOffset - this.touchXYPair[0]) : 0;
				int right = left + v.getWidth();
				int top = isHorizontal() ? 0 : (yOffset - this.touchXYPair[1]);
				int bottom = top + v.getHeight();
				
				if(isHorizontal()){
	                if (left < 0) {
	                    left = 0;
	                    right = left + v.getWidth();
	                }
	                if (right > getMeasuredWidth()) {
	                    right = getMeasuredWidth();
	                    left = right - v.getWidth();
	                }
				}else{
	                if (top < 0) {
	                    top = 0;
	                    bottom = top + v.getHeight();
	                }

	                if (bottom > getMeasuredHeight()) {
	                    bottom = getMeasuredHeight();
	                    top = bottom - v.getHeight();
	                }
				}
				v.layout(left, top, right, bottom);
				v.postInvalidate();
				break;
		}
		return false;
	}

	@Override
	public void onClick(View view) {
		this.currPos = (Integer)view.getTag();
		if(this.tvItem[this.currPos].isClickable()){
			this.tvItem[this.lastPos].setClickable(true);
			this.tvItem[this.currPos].setClickable(false);
			moveTo((this.lastPos - this.currPos) * this.indicatorLength);
			
			this.lastPos = this.currPos;
			if(null != this.onItemClickListener){
				this.onItemClickListener.onItemClick(view, this.currPos);
			}
		}
	}

	@Override
	protected void onFinishInflate(){
		super.onFinishInflate();
		setBackgroundResource(this.background);
		this.itemText = (0 != arrayId) ? 
				getResources().getStringArray(this.arrayId) :
				new String[]{};
	}
	
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
        if (this.currPos > this.itemText.length - 1) {
            throw new IllegalArgumentException("The position can't be great than the count of items!");
        }
        final LinearLayout layout = new LinearLayout(this.context);
        layout.setOrientation(isHorizontal() ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
        LinearLayout.LayoutParams itemParams = new LinearLayout.LayoutParams(isHorizontal() ? 0 : getMeasuredWidth(),
                isHorizontal() ? getMeasuredHeight() : 0);
        itemParams.weight = 1;
        itemParams.gravity = Gravity.CENTER;
        for (int i = 0; i < itemText.length; i++) {
            TextView item = new TextView(this.context);
            item.setTag(i);
            item.setText(itemText[i]);
            item.setTextSize(textSize);
            item.setTextColor(textColor);
            item.setGravity(Gravity.CENTER);
            item.setOnClickListener(this);
            item.setClickable(currPos != i);
            tvItem[i] = item;
            layout.addView(item, itemParams);
        }

        this.lastPos = this.currPos;
        indicatorLength = (isHorizontal() ? getMeasuredWidth() : getMeasuredHeight()) / itemText.length;
        final LinearLayout.LayoutParams indicatorParams = new LinearLayout.LayoutParams(isHorizontal() ? indicatorLength
                : getMeasuredWidth(), isHorizontal() ? getMeasuredHeight() : indicatorLength);

        this.ivIndicator = new ImageView(this.context);
        this.ivIndicator.setBackgroundResource(this.bgIndicator);
        this.ivIndicator.setOnTouchListener(this);
        this.ivIndicator.setClickable(true);

        final LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(getMeasuredWidth(), getMeasuredHeight());
        post(new Runnable() {
            @Override
            public void run() {
                TabSwitcher.this.addView(ivIndicator, indicatorParams);
                TabSwitcher.this.addView(layout, layoutParams);
            }
        });
        invalidate();
        postInvalidate();
	}

	private void init(){
		this.context = getContext();
		FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT,
				FrameLayout.LayoutParams.WRAP_CONTENT);
		setLayoutParams(params);
	}
	
	private boolean isHorizontal(){
		return this.orientation == HORIZONTAL;
	}
	
	private void moveTo(float fromDelta){
		TranslateAnimation animation = null;
		if(isHorizontal()){
			ivIndicator.layout(currPos * indicatorLength, 
					ivIndicator.getTop(), 
					currPos * indicatorLength + ivIndicator.getWidth(), 
					ivIndicator.getBottom());
			 animation = new TranslateAnimation(fromDelta, 0, 0, 0);
		}else{
            ivIndicator.layout(ivIndicator.getLeft(), 
            		currPos * indicatorLength, 
            		ivIndicator.getRight(), 
            		currPos * indicatorLength + ivIndicator.getHeight());
            animation = new TranslateAnimation(0, 0, fromDelta, 0);
		}
		animation.setInterpolator(this.interpolator);
		animation.setDuration(SWITCH_DURATION);
		animation.setFillAfter(true);
		this.ivIndicator.startAnimation(animation);
	}
	
	private void moveToAppropriatePosition(){
		int srcPos = isHorizontal() ? ivIndicator.getLeft() : ivIndicator.getTop();
		this.currPos = Math.round((float)srcPos / this.indicatorLength);
		int destPos = this.currPos * indicatorLength;
		moveTo(srcPos - destPos);
	}
}
